import { FieldInfo, MysqlError, PoolConnection } from "mysql";
import { Application } from "pinus";
import { Dao } from "./dao";


export default function (app: Application) {
    return new UserDao(app)
}

export class UserDao extends Dao {

    public constructor(app: Application) {
        super(app)
    }

    public getHallUserInfoById(id: number) {
        const sql = 'SELECT u.id, u.username, c.coin from ums_user u INNER JOIN ums_coin c  ON u.id = c.user_id WHERE u.id = ? and game_lock = 0'
        const args = [id]
        return this.select(sql, args)
    }

    //需要调整   TODO...
    public getGameClientUrl() {
        const sql = 'select value from cms_system_config where `key`="GameUrl"'
        const args = []
        return this.select(sql, args)
    }

    public getUserInfoBychannel_id(channelId: string) {
        const sql = 'SELECT id from ums_user WHERE channel_id= ?'
        const args = [channelId]
        return this.select(sql, args)
    }
    public createUserReturnId(values: any) {
        let sql = 'insert into ums_user(channel_id,username,status,online,expand) values ( ? , ? , ? , ? , ? )'
        this.insert(sql, [values.channel_id, values.username, '0', '0', values.expand])

        let sql1 = 'insert into ums_coin(user_id,coin,currency,currency_num,is_lock) values( ' +
            '(select id  from ums_user where channel_id= ? ), ? , ? , ? , ? )'

        this.insert(sql1, [values.channel_id, '0', values.currency, values.currencyNum, '0'])
    }

    public getUserInfoById(id: number) {
        const sql = 'SELECT u.id, u.username, c.coin, u.status from ums_user u INNER JOIN ums_coin c  ON u.id = c.user_id WHERE u.id = ?'
        const args = [id]
        return this.select(sql, args)
    }

    public getUserInfoBychannelId(channel_id: string) {
        const sql = 'SELECT u.id, u.username, c.coin, u.status from ums_user u INNER JOIN ums_coin c  ON u.id = c.user_id WHERE u.channel_id = ?'
        const args = [channel_id]
        return this.select(sql, args)
    }

    public transformId(channelId: number, username: string) {
        const sql = 'select id from ums_user where channel_id = ? and username = ?'
        const args = [channelId, username]
        return this.select(sql, args)
    }

    public getUserCoinById(id: number) {
        const sql = 'SELECT coin from ums_coin WHERE user_id = ?'
        const args = [id]
        return this.select(sql, args)
    }

    public unlockCoinById(id: number) {
        const sql = 'update ums_coin set is_lock = 0 where user_id = ? and is_lock = 1'
        const args = [id]
        return this.select(sql, args)
    }

    public updateCoinById(id: number, coin: number) {
        const sql = 'update ums_coin set coin = ? where user_id = ? and is_lock = 1'
        const args = [coin, id]
        return this.select(sql, args)
    }

    public updateUserOnlineById(userId: number, online: number) {
        const sql = 'update ums_user set online = ? where id = ?'
        const args = [online, userId]
        return this.select(sql, args)
    }

    /**
     * 加载数据
     */
    public async loadUserInfoById(id: number): Promise<{ results?: any, fields?: FieldInfo[] }> {
        const connection = await this.getConnection()
        try {
            await this.beginTransaction(connection)
        } catch (e) {
            connection.release()
            throw e
        }
        const update = 'update ums_coin set is_lock = 1 where user_id = ? and is_lock = 0'
        let args = [id]
        try {
            let { results } = await this.update(update, args, connection)
            if (results.affectedRows !== 1) {
                throw 'user data is lock'
            }
            const select = 'SELECT u.id, u.username, c.coin, u.channel_id as channelId, u.expand from ums_user u INNER JOIN ums_coin c  ON u.id = c.user_id WHERE u.id = ?'
            args = [id]
            let selectResult = await this.select(select, args, connection)
            if (selectResult.results.length !== 1) {
                throw 'user data error'
            }
            await this.commit(connection)
            connection.release()
            return selectResult
        } catch (e) {
            await this.rollback(connection)
            connection.release()
            throw e
        }
    }

    async updateCoin(userId: number, userCoin: number, coin: number) {
        const totalCoin = userCoin + coin
        const sql = 'update ums_coin set coin = ? where user_id = ? and is_lock = 1 and coin = ?'
        const args = [totalCoin, userId, userCoin]
        return this.select(sql, args)
    }

    async decreaseCoin(userId: number, userCoin: number, coin: number) {
        let totalCoin = userCoin + coin
        if (coin === 0) {
            totalCoin = 0
        }
        const sql = 'update ums_coin set coin = ? where user_id = ? and is_lock = 1 and coin = ?'
        const args = [totalCoin, userId, userCoin]
        return this.select(sql, args)
    }

    public getChannelInfos() {
        const sql = 'SELECT id as channelId, notify_url as notifyUrl, offline_url as offlineUrl   from mms_channel'
        const args = []
        return this.select(sql, args)
    }

    async updateCoinAndUnlock(userId: number, coin: number) {
        const sql = 'update ums_coin set coin = ?, is_lock = 0 where user_id = ? and is_lock = 1'
        const args = [coin, userId]
        return this.select(sql, args)
    }
}
